#include "linkchecker.h"

static const QStringList scTLD(QStringList()
                              << "aero" << "asia" << "biz" << "cat"
                              << "com" << "coop" << "edu" << "gov"
                              << "info" << "int" << "jobs" << "mil"
                              << "mobi" << "museum" << "name" << "net"
                              << "org" << "pro" << "tel" << "travel");

static const QStringList scSuffixCandidate(QStringList()
                                           << "exe" << "rar" << "zip" << "7z");

void loadBlackList()
{
    hasBlackList = false;
    QFile file("./blacklist.txt");
    if(file.open(QIODevice::ReadOnly))
    {
        QTextStream in(&file);
        blacklist = in.readAll().split("\r\n", QString::SkipEmptyParts);
        hasBlackList = true;
    }
    else
    {
        QMessageBox::warning(NULL, QObject::tr("Warning"), QObject::tr("blacklist.txt file not exists."), QMessageBox::Ok);
        hasBlackList = true;
    }
}

LinkChecker::LinkChecker()
{
}

bool LinkChecker::isExLink(const QUrl &linkUrl, const QUrl &currentUrl)
{
    QStringList linkSections = linkUrl.host().split('.');
    QStringList currentSections = currentUrl.host().split('.');
    if(linkSections.last().length() == 2)   //  ccTLD
    {
        if(linkSections.last() == currentSections.last())   //  ccTLD matched, and need to match gTLD
        {
            int lsCount = linkSections.count();
            int csCount = currentSections.count();
            if(scTLD.contains(linkSections[lsCount - 2])
                && scTLD.contains(currentSections[csCount - 2])) //  gTLD
            {
                if(linkSections[lsCount - 2] == currentSections[csCount - 2])   //  gTLD matched, and need to match host name
                {
                    if(linkSections[lsCount - 3] == currentSections[csCount - 3]) return false;
                    else return true;
                }
                else return true;
            }
            else
            {
                if(linkSections[lsCount - 2] == currentSections[csCount - 2]) return false;
                else return true;
            }
        }
        else return true;
    }
    else    //  no ccTLD
    {
        if(linkSections.last() == currentSections.last())   //  gTLD matched, and need to match host name
        {
            int lsCount = linkSections.count();
            int csCount = currentSections.count();
            if(linkSections[lsCount - 2] == currentSections[csCount - 2]) return false;
            else return true;
        }
        else return true;
    }
}

bool LinkChecker::isFileLink(const QUrl &linkUrl)
{
    //  Direct link to file
    if(scSuffixCandidate.contains(linkUrl.path().right(3))) return true;

    //  File path is in query items
    QList<QPair<QString, QString> > queryItems = linkUrl.queryItems();
    for(int i = 0; i < queryItems.count(); i++)
    {
        QString value = queryItems[i].second;
        if(scSuffixCandidate.contains(value.right(3))) return true;
    }

    return false;
}

//  Check if the url is in blacklist
bool LinkChecker::isAdLink(const QUrl &linkUrl)
{
    for(int i = 0; i < blacklist.count(); i++)
    {
        QString url = linkUrl.toString();
        if(url.contains(blacklist[i])) return true;
    }

    return false;
}

//  Check if this url is a legal link
bool LinkChecker::check(const QUrl &linkUrl, const QUrl &currentUrl)
{
    if(!hasBlackList) loadBlackList();

    if(hasBlackList && isAdLink(linkUrl)) return false;
    else
    {
        if(!isExLink(linkUrl, currentUrl))
            return true;
        else if(!isFileLink(linkUrl))
            return true;
        else return false;
    }
}
